package cn.jinbyte.core.utils;

import cn.hutool.core.util.HexUtil;
import cn.hutool.crypto.BCUtil;
import cn.hutool.crypto.SmUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.SM2;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.UtilityClass;
import org.apache.commons.lang3.Strings;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;

/**
 * Sm2非对称加密工具类
 *
 * @author jinty
 * @since 2024/4/26
 */
@UtilityClass
public class Sm2Utils {

    /**
     * 获取默认的SM2密钥对
     *
     * <ul>
     * <li>创建人：jintingying </li>
     * <li>创建时间：2024/5/10 </li>
     * <li>修改备注：</li>
     * </ul>
     *
     * @return com.medicom.crms.common.utils.Sm2Utils.KeyPair
     */
    public static KeyPair createKeyPair() {
        SM2 sm2 = SmUtil.sm2();
        String privateKeyHex = HexUtil.encodeHexStr(BCUtil.encodeECPrivateKey(sm2.getPrivateKey()));
        String publicKeyHex = HexUtil.encodeHexStr(((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false));
        return new KeyPair(privateKeyHex, publicKeyHex);
    }

    /**
     * 使用公钥加密
     *
     * <ul>
     * <li>创建人：jintingying </li>
     * <li>创建时间：2024/5/10 </li>
     * <li>修改备注：</li>
     * </ul>
     *
     * @param publicKey 公钥串
     * @param oriStr    原始数据串
     * @return java.lang.String
     */
    public static String encryptByPublicKey(String publicKey, String oriStr) {
        SM2 sm2 = SmUtil.sm2(null, publicKey);
        return sm2.encryptHex(oriStr, KeyType.PublicKey);
    }

    /**
     * 私钥解密
     *
     * <ul>
     * <li>创建人：jintingying </li>
     * <li>创建时间：2024/5/10 </li>
     * <li>修改备注：</li>
     * </ul>
     *
     * @param privateKey 私钥串
     * @param encryptStr 加密串
     * @return java.lang.String 解密串
     */
    public static String decryptByPrivateKey(String privateKey, String encryptStr) {
        // edit by jintingying on 2024/5/10 - 前端加密后的字符串传过来带了双引号

        if (Strings.CS.contains(encryptStr, "\"")) {
            encryptStr = encryptStr.replaceAll("\"", "");
        }
        SM2 sm2 = SmUtil.sm2(privateKey, null);
        if (!Strings.CS.startsWith(encryptStr, "04")) {
            encryptStr = "04" + encryptStr;
        }
        return sm2.decryptStr(encryptStr, KeyType.PrivateKey);
    }


    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class KeyPair {
        private String privateKey;
        private String publicKey;
    }
}
